package me.numark.net;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.toolbox.HttpHeaderParser;

import android.text.TextUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;

import me.numark.utils.LogUtils;
import me.numark.utils.Settings;

/**
* Created by tian on 14/11/3:下午2:51.
*/
public class GsonRequest<T> extends Request<T> {

    private final Gson gson = new Gson();

    private final Class<T> clazz;

    private final Response.Listener<T> listener;

    private String cacheFile;

    private boolean needsAuthenticate;

    private Map<String, String> params = null;

    public void setCacheFile(String cacheFile) {
        this.cacheFile = cacheFile;
    }

    public GsonRequest(String url, int method, Class<T> clazz, boolean needsAuthenticate,
            Map<String, String> body, Response.Listener<T> listener,
            Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.clazz = clazz;
        this.needsAuthenticate = needsAuthenticate;
        this.listener = listener;
        this.params = body;
    }


    public static String getQueryString(Map<String, String> params) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (!TextUtils.isEmpty(entry.getValue())) {
                try {
                    sb.append(entry.getKey()).append("=")
                            .append(URLEncoder.encode(entry.getValue(), "utf-8"))
                            .append("&");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        }
        sb = sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        return params;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = new LinkedHashMap<String, String>();
        headers.put("uid", Settings.getUid());
        headers.put("token", Settings.getToken());
        return needsAuthenticate ? headers : super.getHeaders();
    }

    @Override
    protected void deliverResponse(T response) {
        if (listener != null) {
            listener.onResponse(response);
        }
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        try {
            //TODO: shall I change the default charset to utf-8 ???
            String json = new String(response.data, HttpHeaderParser
                    .parseCharset(response.headers));
            LogUtils.d("response string:" + json);
            long timeStart = System.currentTimeMillis();
            T fromJson = gson.fromJson(json, clazz);
            long timeEnd = System.currentTimeMillis();
            LogUtils.d("parse time: " + (timeEnd - timeStart));
            return Response
                    .success(fromJson, HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            return Response.error(new ParseError(e));
        }
    }
}
